package com.apes.scm.pur.purchaseReturn.service;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.jpa.spec.model.Filter;
import com.apes.framework.jpa.spec.model.Group;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.Arith;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apes.scm.account.account.model.InventoryBatch;
import com.apes.scm.account.account.model.Stock;
import com.apes.scm.account.account.repository.InventoryBatchRepository;
import com.apes.scm.account.account.repository.StockRepository;
import com.apes.scm.account.account.service.InventoryService;
import com.apes.scm.account.account.service.ProductAccountService;
import com.apes.scm.account.ledger.service.LedgerService;
import com.apes.scm.invoice.model.Invoice;
import com.apes.scm.invoice.repository.InvoiceRepository;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.masterdata.product.model.Product;
import com.apes.scm.masterdata.product.repository.ProductRepository;
import com.apes.scm.pur.purchaseOrder.model.PurchaseOrder;
import com.apes.scm.pur.purchaseOrder.repository.PurchaseOrderRepository;
import com.apes.scm.pur.purchaseReturn.model.PurchaseReturn;
import com.apes.scm.pur.purchaseReturn.model.PurchaseReturnItem;
import com.apes.scm.pur.purchaseReturn.repository.PurchaseReturnRepository;
import com.apes.scm.rbac.repository.PostRepository;
import com.apes.scm.stock.transfer.model.Pick;
import com.apes.scm.stock.transfer.model.PickItem;
import com.apes.scm.stock.transfer.repository.PickRepository;
import com.apes.scm.voucher.model.Voucher;
import com.apes.scm.voucher.model.VoucherItem;
import com.apes.scm.voucher.repository.VoucherItemRepository;
import com.apes.scm.voucher.repository.VoucherRepository;
import com.apes.scm.yy.QueryCommonService;
import org.hibernate.query.internal.NativeQueryImpl;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Service("purchaseReturnService")
public class PurchaseReturnService extends DomainService {

    @Autowired
    PurchaseReturnRepository purchaseReturnRepository;

    @Autowired
    ProductAccountService productAccountService;

    @Autowired
    InventoryBatchRepository inventoryBatchRepository;

    @Autowired
    StockRepository stockRepository;

    @Autowired
    EntityManager entityManager;
    @Autowired
    PickRepository pickRepository;
    @Autowired
    InvoiceRepository invoiceRepository;

    @Autowired
    InventoryService inventoryService;
    @Autowired
    private QueryCommonService queryCommonService;
    @Autowired
    private PartyRoleRepository partyRoleRepository;
    @Autowired
    private VoucherItemRepository voucherItemRepository;

    /*
     * 创建返厂订单
     * @params request
     * */
    public PurchaseReturn create(SimpleRequest request) {
        PurchaseReturn purchaseReturn = request.getO(PurchaseReturn.class);
        // 保存返厂订单
        purchaseReturn = save(purchaseReturn);

        // 减少商品可用数， 增加批次冻结数量
        updateProductAvailableAndBatch(purchaseReturn, false, "创建返厂订单");

        //入库冲红冻结账单
        if (purchaseReturn.getScene().getId().equals("PR002")) {
            invoiceFreeze(purchaseReturn, true);
        }

        return purchaseReturn;
    }

    /*
     * 保存返厂订单
     * */
    private PurchaseReturn save(PurchaseReturn purchaseReturn) {
        // 设置单据状态
        purchaseReturn.setState("sent");
        // 设置创建时间
        if (purchaseReturn.getCreateDate() == null) {
            purchaseReturn.setDateOrder(new Date());
        } else {
            purchaseReturn.setUpdateDate(new Date());
        }

        // 判断明细中的合作方式和主表中的合作方式是否一致，不一致就报错
        boolean flag = purchaseReturn.getPurchaseReturnItems().stream()
                .anyMatch( purchaseReturnItem -> !purchaseReturn.getCooperation().getId().equals(purchaseReturnItem.getInventoryBatch().getCooperation().getId()));
        if (flag) throw new RuntimeException("明细中的合作方式和主表中的合作方式不一致，请重新选择");

        // 设置开票状态
        purchaseReturn.setInvoiceStatus("no");
        // 重新计算主表 合计， 税金等问题
        purchaseReturn.computeAmt();
        return purchaseReturnRepository.saveAndFlush(purchaseReturn);
    }

    /*
     * 更新返厂订单
     * */
    public PurchaseReturn update(SimpleRequest request) {
        // 获取单据原信息
        PurchaseReturn oldPurchaseReturn = getValidPurchaseReturn(request);

        // 还原商品可用数，商品批次冻结数量
        updateProductAvailableAndBatch(oldPurchaseReturn, true, "更新返厂订单");

        //还原账单状态
        if (oldPurchaseReturn.getScene().getId().equals("PR002")) {
            invoiceFreeze(oldPurchaseReturn, false);
        }

        PurchaseReturn purchaseReturn = request.getO(PurchaseReturn.class);

        // 重新下可用数，批次冻结数量
        updateProductAvailableAndBatch(purchaseReturn, false, "更新返厂订单");

        //重新冻结账单状态
        if (purchaseReturn.getScene().getId().equals("PR002")) {
            invoiceFreeze(purchaseReturn, true);
        }

        // 更新订单信息 （目前按创建情况更新信息）
        purchaseReturn = save(purchaseReturn);

        return purchaseReturn;
    }


    /*
     * 删除返厂订单
     * */
    public String delete(SimpleRequest request) {
        // 获取有效订单信息
        PurchaseReturn purchaseReturn = getValidPurchaseReturn(request);

        // 增加商品可用数，减少商品批次冻结数量
        updateProductAvailableAndBatch(purchaseReturn, true, "删除返厂订单");


        //还原账单状态
        if (purchaseReturn.getScene().getId().equals("PR002")) {
            invoiceFreeze(purchaseReturn, false);
        }
        purchaseReturn.setState("delete");
        // 删除数据
        purchaseReturnRepository.saveAndFlush(purchaseReturn);
        return "删除成功！";
    }

    /**
     * 发起返厂申请
     *
     * @param request
     * @return
     */
    public PurchaseReturn apply(SimpleRequest request) {
        // 获取有效订单信息
        PurchaseReturn purchaseReturn = getValidPurchaseReturn(request);
        purchaseReturn.setState("apply");
        return purchaseReturnRepository.saveAndFlush(purchaseReturn);
    }

    /**
     * 驳回返厂申请
     *
     * @param request
     * @return
     */
    public PurchaseReturn reject(SimpleRequest request) {
        // 获取有效订单信息
        PurchaseReturn purchaseReturn = getValidPurchaseReturn(request);

        // 增加商品可用数，减少商品批次冻结数量
        updateProductAvailableAndBatch(purchaseReturn, true, "删除返厂订单");


        //还原账单状态
        if (purchaseReturn.getScene().getId().equals("PR002")) {
            invoiceFreeze(purchaseReturn, false);
        }
        // 删除数据
        purchaseReturnRepository.saveAndFlush(purchaseReturn);
        return purchaseReturn;
    }


    /*
     * 终止返厂订单(暂未考虑终止流程)
     * */
    public PurchaseReturn cancel(SimpleRequest request) {
        // 获取有效订单信息
        PurchaseReturn purchaseReturn = getValidPurchaseReturn(request);
        // todo
        List<Pick> picks = pickRepository.findAll(JpaDsl.toCriteriaByEq("origin", purchaseReturn.getId(), "state", "confirmed"));
        if (picks.size() > 0) {
            Pick pick = picks.get(0);
            // 增加商品可用数，减少商品批次冻结数量
            updateProductAvailableAndBatch(purchaseReturn, true, "删除返厂订单");

            //还原账单状态
            if (purchaseReturn.getScene().getId().equals("PR002")) {
                invoiceFreeze(purchaseReturn, false);
            }

            JSONArray pickItemArray = new JSONArray();
            JSONObject cancelPick = new JSONObject();
            cancelPick.put("id", purchaseReturn.getId());
            cancelPick.put("innerBusinessType", purchaseReturn.getInnerBusinessType());
            for (PickItem nPickItem : pick.getPickItems()) {
                JSONObject pickItemObj = new JSONObject();
                for (PurchaseReturnItem nPurchaseReturnItems : purchaseReturn.getPurchaseReturnItems()) {
                    if (nPickItem.getProduct().getId().equals(nPurchaseReturnItems.getProduct().getId()) && nPickItem.getOriginLine().equals(nPurchaseReturnItems.getId() + "")) {
                        pickItemObj.put("id", nPurchaseReturnItems.getId());
                        double productReturnQty = nPurchaseReturnItems.getProductReturnQty();
                        double canCancelQty = nPurchaseReturnItems.getProductReturnQty() - nPurchaseReturnItems.getQtyReceived() - nPurchaseReturnItems.getCancelQty();
                        if (canCancelQty > productReturnQty) throw new RuntimeException("可终止数量不能大于返厂数");
                        pickItemObj.put("cancelQty", canCancelQty);
                        nPurchaseReturnItems.setCancelQty(canCancelQty);
                        break;
                    }
                }
                pickItemArray.add(pickItemObj);
            }
            cancelPick.put("items", pickItemArray);
            invoke("stock.pick.cancel", cancelPick);

            purchaseReturn.setState("cancel");
            purchaseReturn.setDateCancel(new Date());
            purchaseReturn.setCancelUId(getPerson(request));
            purchaseReturnRepository.saveAndFlush(purchaseReturn);
        }
        return purchaseReturn;
    }

    /*
     *  返厂订单审核
     * */
    public PurchaseReturn approve(SimpleRequest request) {
        // 获取有效订单信息
        PurchaseReturn purchaseReturn = getValidPurchaseReturn(request);
        // 获取未发货的非服务商品
        List<PurchaseReturnItem> physical = purchaseReturn.queryPhysicalProduct();

        if (physical.size() == 0) {
            // 发货状态
            purchaseReturn.setShipped(true);
        }

        // 更新单据状态
        purchaseReturn.setState("approve");
        if (purchaseReturn.getApproveUid() == null) purchaseReturn.setApproveUid(request.getPerson());
        // 设置审核时间
        purchaseReturn.setDateApprove(new Date());
        // 更新订单信息
        purchaseReturn = purchaseReturnRepository.saveAndFlush(purchaseReturn);

        // 创建交货单
        /*if(physical.size() != 0) {
            createPick(purchaseReturn,physical);
        }else {
            // 说明全部为服务商品, 订单已为发货状态, 创建采购退回凭证
            createVoucher(purchaseReturn, null);
        }*/


        return purchaseReturn;
    }


    /*
     * 获取有效订单信息
     * */
    private PurchaseReturn getValidPurchaseReturn(SimpleRequest simpleRequest) {
        PurchaseReturn purchaseReturn = purchaseReturnRepository.findOne((String) simpleRequest.get("id"));
        if (purchaseReturn == null)
            throw new RuntimeException("返厂订单：" + (String) simpleRequest.get("id") + " 在系统中不存在!");
        if ((int) simpleRequest.get("version") != purchaseReturn.getVersion())
            throw new RuntimeException("返厂订单已发生改变,请重新查询返厂订单状态！");
        return purchaseReturn;
    }

    /*
     * 更新商品库存可用数，批次表冻结数量
     * @parmas
     * PurchaseReturn 订单信息
     * isAdd true代表 增加可用数， false 代表减少可用数
     * note 备注
     * */
    private void updateProductAvailableAndBatch(PurchaseReturn purchaseReturn, boolean isAdd, String note) {
        for (PurchaseReturnItem item : purchaseReturn.getPurchaseReturnItems()) {
            double changeQty = 0;
            if (isAdd) {
                changeQty = Math.abs(item.getProductReturnQty());
            } else {
                changeQty = -1 * Math.abs(item.getProductReturnQty());
            }
            // 减少（增加）商品可用数
            productAccountService.setProductAvailable(item.getProduct(), purchaseReturn.getLocation(), item.getUom(), changeQty, purchaseReturn.getInnerBusinessType(), purchaseReturn.getId(), String.valueOf(item.getId()), note, purchaseReturn.getCompany());

            // 增加（减少）商品价值（商品批次） 的冻结数量
            // 查询批次信息
            InventoryBatch inventoryBatch = inventoryBatchRepository.findOne(item.getInventoryBatch().getId());
            //  增加（减少）冻结数量
            //inventoryBatch.changeFrostQty(-1 * changeQty);
            inventoryService.changeFrostQty(inventoryBatch, item.getUom(), -1 * changeQty, purchaseReturn.getCompany(), purchaseReturn.getInnerBusinessType(), purchaseReturn.getId(), String.valueOf(item.getId()), note);
        }
    }

    /**
     * 冻结/解冻账单
     *
     * @param purchaseReturn
     * @param isAdd
     */
    private void invoiceFreeze(PurchaseReturn purchaseReturn, boolean isAdd) {
        List<Invoice> invoices = invoiceRepository.findAll(JpaDsl.toCriteriaByEq("origin", purchaseReturn.getPick().getOrigin(), "originBusinessType", purchaseReturn.getPick().getOriginBusinessType()));
        if (invoices.size() > 0) {
            invoices.forEach(invoice -> {
                if (isAdd) {
                    invoice.freeze();
                    invoice.checkWriteOff();
                } else {
                    invoice.thaw();
                    invoice.checkWriteOff();
                }
            });
        }

    }

    /**
     * 账单冲销
     *
     * @param request
     */
    private void invoiceWriteOff(SimpleRequest request) {
        Voucher voucher = request.getO(Voucher.class);
        PurchaseReturn purchaseReturn = purchaseReturnRepository.findOne(voucher.getOrigin());
        List<Invoice> invoices = invoiceRepository.findAll(JpaDsl.toCriteriaByEq("origin", purchaseReturn.getPick().getOrigin(), "originBusinessType", purchaseReturn.getPick().getOriginBusinessType()));
        if (invoices.size() > 0) {
            invoices.forEach(invoice -> {
                invoke("invoice.writeOff", MapUtil.mapped(invoice));
            });
        }

    }

    /**
     * 获取入库单
     *
     * @return
     */
    private Page<Pick> findPick(SimpleRequest request) {
        List<Map> condition = request.get("condition");
        JSONObject model = new JSONObject();
        condition.forEach(filter -> {
            model.put((String) filter.get("field"), filter.get("value"));
        });
        // 来源为'交货单'，该交货单的上级来源为采购订单； 交货单对应的批次结存没有被消耗；交货单对应的账单没有被使用
        StringBuffer pick_buffer = new StringBuffer();
        pick_buffer.append("SELECT ID " +
                "FROM STOCK_PICK " +
                "WHERE STATE ='done' AND ID not IN ( " +
                "    SELECT  DISTINCT s.ID " +
                "    FROM STOCK_PICK S, ACC_VOUCHER A,ACC_VOUCHER_ITEM C " +
                "    WHERE S.ID = A.SOURCE AND A.ID = C.VOUCHER_ID " +
                "      AND A.SOURCE_BUSINESS_TYPE = 'Pick' " +
                "      AND S.ORIGIN_BUSINESS_TYPE = 'PurchaseOrder' " +
                "      AND A.ORIGIN_BUSINESS_TYPE = 'PurchaseOrder' " +
                "      AND a.ORIGIN = S.ORIGIN " +
                "      AND ( " +
                "      EXISTS(SELECT 1 FROM ACC_INVENTORY_BATCH I " +
                "                  WHERE I.BATCH_NUMBER = C.ID " +
                "                    AND (I.PURCHASE_QTY != I.BALANCE_QTY " +
                "                      OR I.FROST_QTY <> 0)) " +
                "      ) " +
                "    UNION ALL " +
                "    SELECT s.ID " +
                "    FROM STOCK_PICK S, ACC_VOUCHER A,ACC_VOUCHER_ITEM C " +
                "    WHERE S.ID = A.SOURCE AND A.ID = C.VOUCHER_ID " +
                "      AND A.SOURCE_BUSINESS_TYPE = 'Pick' " +
                "      AND S.ORIGIN_BUSINESS_TYPE = 'PurchaseOrder' " +
                "      AND A.ORIGIN_BUSINESS_TYPE = 'PurchaseOrder' " +
                "      AND a.ORIGIN = S.ORIGIN " +
                "      AND ( EXISTS(SELECT 1 " +
                "                  FROM ACC_INVOICE AI, " +
                "                       ACC_INVOICE_ITEM AII " +
                "                  WHERE AI.ORIGIN = S.ORIGIN " +
                "                    AND AI.ID = AII.INVOICE_ID " +
                "                    AND (AII.FREEZE_QTY<>0 OR AII.SETTLED_QTY<>0))) " +
                "        ) AND ORIGIN_BUSINESS_TYPE = 'PurchaseOrder'");
        if (model.containsKey("id")) {
            pick_buffer.append(" AND ( ");
            pick_buffer.append("  ID =").append(model.getString("id"));
            pick_buffer.append("  OR ORIGIN =").append(model.getString("id"));
            pick_buffer.append("  OR SOURCE =").append(model.getString("id"));
            pick_buffer.append("  )");
        }
        pick_buffer.append(" AND  COMPANY_ID = '").append(SpringManager.getBean(PostRepository.class).findOne(request.getPostId()).getCompany().getId()).append("'");
        if (model.containsKey("location.id")) {
            pick_buffer.append(" AND LOCATION_ID LIKE '%").append(model.getString("location.id")).append("%'");
        }
        if (model.containsKey("product.id")) {
            pick_buffer.append(" ID IN (SELECT 1 FROM STOCK_PICK_ITEM B WHERE ID = B.PICK_ID AND B.PRODUCT_ID ='").append(model.getString("product.id")).append("')");
        }
        Query query = entityManager.createNativeQuery(pick_buffer.toString());
        query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();
        List<Map> picks = query.getResultList();
        if (picks.isEmpty()) return null;
        List<String> pickIds = picks.stream().map(pick -> pick.get("ID").toString()).collect(Collectors.toList());
        Group group = new Group();
        group.addFilters(
                JpaDsl.toFilter(
                        "id", "in", pickIds
                )
        );
        Page<Pick> pickPage = pickRepository.findAll(group.build(false), PageRequest.of(request.get("page"), request.get("size")));
        return pickPage;
    }

    /**
     * 根据交货单查找采购单 并填充入库批次
     *
     * @param request
     * @return
     */
    public List<HashMap> findOrderByPick(SimpleRequest request) {
        String id = request.get("id");
        PurchaseOrder order = SpringManager.getBean(PurchaseOrderRepository.class).findOne(id);
        List<Voucher> vouchers = SpringManager.getBean(VoucherRepository.class).findAll(JpaDsl.toCriteriaByEq("origin", id, "originBusinessType", "PurchaseOrder"));
        HashMap orderMap = MapUtil.mapped(order);
        List  purchaseItems = (List)orderMap.get("purchaseItems");
        List<HashMap> returnData = new ArrayList();
        for (int i = 0; i < purchaseItems.size(); i++) {
            for (Voucher voucher:vouchers) {
                HashMap purchaseOrderItemClone = (HashMap) ((HashMap) purchaseItems.get(i)).clone();

                //根据采购订单明细 查找入库批次
                VoucherItem voucherItem = voucherItemRepository.findOne(JpaDsl.toCriteriaByEq("voucher.id", voucher.getId(), "originItemId", purchaseOrderItemClone.get("id"))).orElse(null);
                if (Objects.isNull(voucherItem)) continue;
                InventoryBatch inventoryBatch = inventoryBatchRepository.findOne(JpaDsl.toCriteriaByEq("batchNumber", voucherItem.getId())).orElse(new InventoryBatch());
                if (inventoryBatch.getBalanceQty() == 0) continue;

                // 查找商品库存帐
                Stock stock = stockRepository.findFirstByProductIdAndLocationIdAndUsableQtyGreaterThan((String) ((HashMap)(purchaseOrderItemClone.get("product"))).get("id"), order.getLocation().getId(), 0);
                if (Objects.isNull(stock) || stock.getUsableQty() == 0) continue;

                // 赋值
                double qtyUse = (inventoryBatch.getBalanceQty() - inventoryBatch.getFrostQty()) > (stock.getUsableQty() - stock.getFrozenQty())?
                        (stock.getUsableQty() - stock.getFrozenQty()):(inventoryBatch.getBalanceQty() - inventoryBatch.getFrostQty());
                purchaseOrderItemClone.put("name", inventoryBatch.getInnerBusinessKey());
                purchaseOrderItemClone.put("inventoryBatch", inventoryBatch);
                purchaseOrderItemClone.put("productSumQty", qtyUse);
                purchaseOrderItemClone.put("voucherOrigin", id); // 这里直接使用 id 作为值，是因为只会是采购订单单号
                returnData.add(purchaseOrderItemClone);
            }
        }
        if (returnData.isEmpty()) throw new RuntimeException("请检查以下数据是否满足条件:<br/> 1.【商品库存帐】是否有可用数！<br/> 2.【商品批次】是否有结存！");
        return returnData;
    }

    /**
     * 获取现金采购订单
     *
     * @return
     */
    private Page<PurchaseOrder> findOrder(SimpleRequest request) {
        Map map = request.getMap();
        List<Map> condition = request.get("condition");
        condition.forEach(filter -> {
            map.put((String) filter.get("field"), filter.get("value"));
        });
        String companyId = SpringManager.getBean(PostRepository.class).findOne(request.getPostId()).getCompany().getId();
        Sort sort = new Sort(Sort.Direction.ASC, "createDate");
        if (map.containsKey("id")) {
            if (map.containsKey("productId")) {
                return SpringManager.getBean(PurchaseOrderRepository.class).findAllByIdAndProductAndSceneAndStateAndCompany((String) map.get("id"), (String) map.get("productId"), "PO003", "done", companyId, PageRequest.of(request.get("page"), request.get("size"), sort));
            }
            return SpringManager.getBean(PurchaseOrderRepository.class).findAllByIdAndSceneAndStateAndCompany((String) map.get("id"), "PO003", "done", companyId, PageRequest.of(request.get("page"), request.get("size"), sort));
        }
        if (map.containsKey("productId")) {
            return SpringManager.getBean(PurchaseOrderRepository.class).findAllByProductAndSceneAndStateAndCompany((String) map.get("productId"), "PO003", "done", companyId, PageRequest.of(request.get("page"), request.get("size"), sort));
        }
        return SpringManager.getBean(PurchaseOrderRepository.class).findAllBySceneAndStateAndCompany("PO003", "done", companyId, PageRequest.of(request.get("page"), request.get("size"), sort));
    }


    /**
     * 返厂查询数据统一接口
     *
     * @param simpleRequest
     * @return
     */
    public Object queryPurchaseReturnData(SimpleRequest simpleRequest) throws ParseException {
        JSONObject getJO = simpleRequest.getJO();
        Group group = getJO.getObject("group", Group.class);
        return this.findOrderMerchant(group, simpleRequest);

    }

    private Map findOrderMerchant(Group group, SimpleRequest request) {
        Sort sort = new Sort(Sort.Direction.DESC, "createDate");
        for (Filter filter : group.getFilters()) {
            if(filter.getField().equals("scene")) {
                filter.setField("scene.id");
                filter.setValue(filter.getValue().equals("PR003") ? "PO003" : "PO002");
            }
        }
        Page<PurchaseOrder> purchaseOrderPage = SpringManager.getBean(PurchaseOrderRepository.class).findAll(group.build(true), PageRequest.of(request.getJO().getInteger("page"), request.getJO().getInteger("size"), sort));
        return MapUtil.mapped(purchaseOrderPage, "purchaseItems");
   }

    private Page<Pick> findPickMerchant(JSONObject param) {
        // 来源为'交货单'，该交货单的上级来源为采购订单； 交货单对应的批次结存没有被消耗；交货单对应的账单没有被使用
        StringBuffer pick_buffer = new StringBuffer();
        pick_buffer.append("SELECT ID " +
                "FROM STOCK_PICK " +
                "WHERE STATE ='done' AND ID not IN ( " +
                "    SELECT  DISTINCT s.ID " +
                "    FROM STOCK_PICK S, ACC_VOUCHER A,ACC_VOUCHER_ITEM C " +
                "    WHERE S.ID = A.SOURCE AND A.ID = C.VOUCHER_ID " +
                "      AND A.SOURCE_BUSINESS_TYPE = 'Pick' " +
                "      AND S.ORIGIN_BUSINESS_TYPE = 'PurchaseOrder' " +
                "      AND A.ORIGIN_BUSINESS_TYPE = 'PurchaseOrder' " +
                "      AND a.ORIGIN = S.ORIGIN " +
                "      AND ( " +
                "      EXISTS(SELECT 1 FROM ACC_INVENTORY_BATCH I " +
                "                  WHERE I.BATCH_NUMBER = C.ID " +
                "                    AND (I.PURCHASE_QTY != I.BALANCE_QTY " +
                "                      OR I.FROST_QTY <> 0)) " +
                "      ) " +
                "    UNION ALL " +
                "    SELECT s.ID " +
                "    FROM STOCK_PICK S, ACC_VOUCHER A,ACC_VOUCHER_ITEM C " +
                "    WHERE S.ID = A.SOURCE AND A.ID = C.VOUCHER_ID " +
                "      AND A.SOURCE_BUSINESS_TYPE = 'Pick' " +
                "      AND S.ORIGIN_BUSINESS_TYPE = 'PurchaseOrder' " +
                "      AND A.ORIGIN_BUSINESS_TYPE = 'PurchaseOrder' " +
                "      AND a.ORIGIN = S.ORIGIN " +
                "      AND ( EXISTS(SELECT 1 " +
                "                  FROM ACC_INVOICE AI, " +
                "                       ACC_INVOICE_ITEM AII " +
                "                  WHERE AI.ORIGIN = S.ORIGIN " +
                "                    AND AI.ID = AII.INVOICE_ID " +
                "                    AND (AII.FREEZE_QTY<>0 OR AII.SETTLED_QTY<>0))) " +
                "        ) AND ORIGIN_BUSINESS_TYPE = 'PurchaseOrder'");
        if (param.containsKey("id")) {
            String id = param.getString("id");
            pick_buffer.append(" AND ( ");
            pick_buffer.append("  ID =").append(id);
            pick_buffer.append("  OR ORIGIN =").append(id);
            pick_buffer.append("  OR SOURCE =").append(id);
            pick_buffer.append("  )");
        }

        pick_buffer.append(" AND  COMPANY_ID = '").append(SpringManager.getBean(PostRepository.class).findOne(param.getString("postId")).getCompany().getId()).append("'");
        if (param.containsKey("location")) {
            pick_buffer.append(" AND LOCATION_ID LIKE '%").append(param.getString("location")).append("%'");
        }
        Query query = entityManager.createNativeQuery(pick_buffer.toString());
        query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();
        List<Map> picks = query.getResultList();
        if (picks.isEmpty()) return null;
        List<String> pickIds = picks.stream().map(pick -> pick.get("ID").toString()).collect(Collectors.toList());
        Group group = new Group();
        group.addFilters(
                JpaDsl.toFilter(
                        "id", "in", pickIds
                )
        );
        Page<Pick> pickPage = pickRepository.findAll(group.build(false), PageRequest.of(param.getInteger("page"), param.getInteger("size")));
        return pickPage;
    }

    /**
     * 返厂明细导入
     *
     * @param request
     * @return
     */
//    public JSONObject beImport(SimpleRequest request) {
//        //Excel信息
//        JSONObject importData = request.get("importData");
//        JSONArray field = (JSONArray) request.get("data");
//        JSONObject exclObject = new JSONObject();                  //返回值
//
//        JSONArray exclArr = new JSONArray();            //行内容
//        JSONArray headerName = new JSONArray();         //头部
//        JSONArray fieldName = new JSONArray();          //field
//        for (Object o : field) {
//            JSONObject webTab = (JSONObject) o;
//            headerName.add(webTab.get("name"));
//            fieldName.add(webTab.get("field"));
//        }
//        //获取model
//        JSONObject model = (JSONObject) request.get("model");
//        String companyId = model.getJSONObject("company").getString("id");
//        String supplierId = model.getJSONObject("supplier").getString("id");
//        String cooperationId = model.getJSONObject("cooperation").getString("id");
//        String locationId = model.getJSONObject("location").getString("id");
//
//        //业务逻辑
//        importData.forEach((k, v) -> {
//
//            //获得value ===Excel内容
//            JSONArray excl = (JSONArray) v;
//            JSONArray header = (JSONArray) excl.get(0); //首行数据
//            String productId;
//            for (int i = 0; i < excl.size(); i++) {  //遍历每一行
//
//                if (i == 0) { //跳过首行
//                    exclArr.add(headerName);
//                    continue;
//                }
//
//                JSONArray lineLong = (JSONArray) excl.get(i); //当前行
//                if (lineLong.size() == 0) {
//                    continue; //跳过空白行
//                }
//                //合并2个list为一个map,KEY为首行数据，Value为当前行数据
//                Map<String, String> rst = IntStream.range(0, header.size()).collect(HashMap::new,
//                        (m, key) -> m.put(header.getString(key).replace(";", ""),
//                                key >= lineLong.size() ? "" : (lineLong.getString(key) == null ? null : lineLong.getString(key).trim().replaceAll("[\\s]{2,}", " "))),
//                        (m1, m2) -> {
//                        });
//                productId = rst.get("商品");
//                double qty = Double.parseDouble(rst.get("返厂数量"));
//                Product product = SpringManager.getBean(ProductRepository.class).findOne(productId);
//                Optional.ofNullable(product).orElseThrow(() -> new RuntimeException(String.format("商品[%s]不存在", rst.get("商品编码"))));
//
//                List<Stock> stocks = stockRepository.findByLocationAndProduct(locationId, productId);
//                double usableQty = stocks.stream().mapToDouble(Stock::getUsableQty).sum();
//                if (stocks.isEmpty() || usableQty < qty) {
//                    throw new RuntimeException(String.format("仓库[%s]商品[%s]库存不够，请检查库存帐！", locationId, productId));
//                }
//
//                //获取批次
//                List<InventoryBatch> inventoryBatches = inventoryBatchRepository.findInventoryByPurchaseReturn(companyId, supplierId, cooperationId, product.getId());
//                double canReturnQtySum = inventoryBatches.stream().mapToDouble(mx -> mx.getBalanceQty() - mx.getFrostQty()).sum();
//                if (inventoryBatches.isEmpty() || canReturnQtySum < qty) {
//                    throw new RuntimeException(String.format("公司[%s]商品[%s]批次可返厂数不够，请检查批次帐！", companyId, productId));
//                }
//                //获取数量足够的批次
//                double finalQty = qty;
//                List<InventoryBatch> batches = inventoryBatches.stream().filter(inventoryBatch -> (inventoryBatch.getBalanceQty() - inventoryBatch.getFrostQty()) >= finalQty).collect(Collectors.toList());
//                if (batches.isEmpty()) {
//                    for (InventoryBatch inventoryBatch : inventoryBatches) {
//                        //计算税金
//                        Map compute = inventoryBatch.getTax().computeAll(inventoryBatch.getCompany(), inventoryBatch.getTaxCostPrice(), inventoryBatch.getBalanceQty() - inventoryBatch.getFrostQty());
//                        //用一个有序的map 封装数据, 防止乱序
//                        double canReturnQty = inventoryBatch.getBalanceQty() - inventoryBatch.getFrostQty();
//                        Map<String, Object> map = new LinkedHashMap<>();
//                        map.put("序号", "");
//                        map.put("批次内码", inventoryBatch);
//                        map.put("商品", product);
//                        map.put("单位", inventoryBatch.getUom());
//                        map.put("库存可用数", usableQty);
//                        map.put("可返厂数量", inventoryBatch.getBalanceQty() - inventoryBatch.getFrostQty());
//                        map.put("返厂数量", Math.min(qty, canReturnQty));
//                        map.put("发货数量", 0);
//                        map.put("单价", inventoryBatch.getTaxCostPrice());
//                        map.put("税金", compute.get("taxAmt"));
//                        map.put("金额", compute.get("totalIncluded"));
//                        map.put("税率", inventoryBatch.getTax());
//                        //将map 转换成 list 利用stream流 引用Map类的getValue方法,弄成一个list
//                        List<Object> valueList = new ArrayList<>(map.values());
//                        exclArr.add(valueList);
//                        qty = qty - canReturnQty;
//                        if (qty <= 0) {
//                            break;
//                        }
//                    }
//                } else {
//                    InventoryBatch inventoryBatch = batches.stream().findFirst().get();
//                    //计算税金
//                    Map compute = inventoryBatch.getTax().computeAll(inventoryBatch.getCompany(), inventoryBatch.getTaxCostPrice(), qty);
//                    //用一个有序的map 封装数据, 防止乱序
//                    Map<String, Object> map = new LinkedHashMap<>();
//                    map.put("序号", "");
//                    map.put("批次内码", inventoryBatch);
//                    map.put("商品", product);
//                    map.put("单位", inventoryBatch.getUom());
//                    map.put("库存可用数", usableQty);
//                    map.put("可返厂数量", inventoryBatch.getBalanceQty() - inventoryBatch.getFrostQty());
//                    map.put("返厂数量", qty);
//                    map.put("发货数量", 0);
//                    map.put("单价", inventoryBatch.getTaxCostPrice());
//                    map.put("税金", compute.get("taxAmt"));
//                    map.put("金额", compute.get("totalIncluded"));
//                    map.put("税率", inventoryBatch.getTax());
//                    //将map 转换成 list 利用stream流 引用Map类的getValue方法,弄成一个list
//                    List<Object> valueList = new ArrayList<>(map.values());
//                    exclArr.add(valueList);
//                }
//
//
//            }
//            exclObject.put(k, exclArr);
//        });
//
//
//        return exclObject;
//    }

    /**
     * 根据编码、其他单据查找
     * @param simpleRequest
     * @return
     */
    public <T> T accordinNumberFind(SimpleRequest simpleRequest) {
        String[] customCondition = {"id", "EQ", "value", "origin", "EQ", "value", "supplierRef", "EQ", "value"};
        return queryCommonService.accordinNumberFindLogic(simpleRequest, purchaseReturnRepository, customCondition, "id", null);
    }

    /**
     * 新返厂明细导入
     * @param request
     * @return
     */
    public JSONObject beImport(SimpleRequest request) {
        //Excel信息
        JSONObject importData = request.get("importData");
        JSONArray field = (JSONArray) request.get("data");
        JSONObject exclObject = new JSONObject();                  //返回值

        JSONArray exclArr = new JSONArray();            //行内容
        JSONArray headerName = new JSONArray();         //头部
        JSONArray fieldName = new JSONArray();          //field
        for (Object o : field) {
            JSONObject webTab = (JSONObject) o;
            headerName.add(webTab.get("name"));
            fieldName.add(webTab.get("field"));
        }
        //获取model
        JSONObject model = (JSONObject) request.get("model");
        String companyId = model.getJSONObject("company").getString("id");
        String supplierId = model.getJSONObject("supplier").getString("id");
        String cooperationId = model.getJSONObject("cooperation").getString("id");
        String locationId = model.getJSONObject("location").getString("id");

        //业务逻辑
        importData.forEach((k, v) -> {
            //获得value ===Excel内容
            JSONArray excl = (JSONArray) v;
            JSONArray header = (JSONArray) excl.get(0); //首行数据
            String productId;
            for (int i = 0; i < excl.size(); i++) {  //遍历每一行

                if (i == 0) { //跳过首行
                    exclArr.add(headerName);
                    continue;
                }

                JSONArray lineLong = (JSONArray) excl.get(i); //当前行
                if (lineLong.size() == 0) {
                    continue; //跳过空白行
                }
                //合并2个list为一个map,KEY为首行数据，Value为当前行数据
                Map<String, String> rst = IntStream.range(0, header.size()).collect(HashMap::new,
                        (m, key) -> m.put(header.getString(key).replace(";", ""),
                                key >= lineLong.size() ? "" : (lineLong.getString(key) == null ? null : lineLong.getString(key).trim().replaceAll("[\\s]{2,}", " "))),
                        (m1, m2) -> {
                        });
                productId = rst.get("商品");
                double qty = Double.parseDouble(rst.get("返厂数量"));
                Product product = SpringManager.getBean(ProductRepository.class).findOne(productId);
                Optional.ofNullable(product).orElseThrow(() -> new RuntimeException(String.format("商品[%s]不存在", rst.get("商品"))));

                //获取商品库存账
                Stock stock = stockRepository.findByLocationIdAndProductId(locationId, productId);
                Optional.ofNullable(stock).orElseThrow(() -> new RuntimeException(String.format("商品[%s]无可返厂数量，请检查", rst.get("商品"))));
                double usableQty = stock.getUsableQty() - stock.getFrozenQty(); //可用数 - 冻结数

                //获取批次
                InventoryBatch inventoryBatch = inventoryBatchRepository.findOne(Long.valueOf(rst.get("批次内码")));
                Optional.ofNullable(inventoryBatch).orElseThrow(() -> new RuntimeException(String.format("查询不到商品[%s]批次[%s]", rst.get("商品"),rst.get("批次内码"))));
                if (!inventoryBatch.getProduct().getId().equals(productId)) throw new RuntimeException(String.format("批次[%s]的商品和商品[%s]不符合", rst.get("批次内码"),rst.get("商品")));
                if (!inventoryBatch.getCompany().getId().equals(companyId)) throw new RuntimeException(String.format("查询不到商品[%s]批次[%s]", rst.get("商品"),rst.get("批次内码")));
                if (!inventoryBatch.getSupplier().getId().equals(supplierId)) throw new RuntimeException(String.format("查询不到商品[%s]批次[%s]", rst.get("商品"),rst.get("批次内码")));

                // 获取来源单号
                List<InventoryBatch> inventoryBatches = this.findInventoryStockMate(Arrays.asList(inventoryBatch), Arrays.asList(stock), new AtomicReference());
                if (!inventoryBatches.isEmpty()) inventoryBatch = inventoryBatches.get(0);

                double balanceQty = inventoryBatch.getBalanceQty() - inventoryBatch.getFrostQty();//结存数-冻结数
                //取最小值
                double min = usableQty > balanceQty?balanceQty:usableQty;
                if (min <= 0) throw new RuntimeException(String.format("商品[%s]无可返厂数量，请检查", rst.get("商品")));

                //计算税金
                Map compute = inventoryBatch.getTax().computeAll(inventoryBatch.getCompany(), inventoryBatch.getTaxCostPrice(), inventoryBatch.getBalanceQty() - inventoryBatch.getFrostQty());
                //用一个有序的map 封装数据, 防止乱序
                Map<String, Object> map = new LinkedHashMap<>();
                map.put("序号", "");
                map.put("批次内码", inventoryBatch);
                map.put("来源单号", inventoryBatch.getVoucherOrigin());
                map.put("商品", product);
                map.put("单位", inventoryBatch.getUom());
                map.put("库存可用数", usableQty);
                map.put("可返厂数量", min);
                map.put("返厂数量", Math.min(qty, min));
                map.put("发货数量", 0);
                map.put("单价", inventoryBatch.getTaxCostPrice());
                map.put("税金", compute.get("taxAmt"));
                map.put("金额", compute.get("totalIncluded"));
                map.put("税率", inventoryBatch.getTax());
                //将map 转换成 list 利用stream流 引用Map类的getValue方法,弄成一个list
                List<Object> valueList = new ArrayList<>(map.values());
                exclArr.add(valueList);
            }

            exclObject.put(k, exclArr);
        });
        return exclObject;
    }

    /**
     * 审核
     * @param
     */
    public Object audit(SimpleRequest request) {
        PurchaseReturn purchaseReturn = request.getO(PurchaseReturn.class);
        String sceneId = purchaseReturn.getScene().getId();
        String cooperationId = purchaseReturn.getCooperation().getId();
        if ("PR001".equals(sceneId) && "distribution".equals(cooperationId)) {
            Map ledgerMoneyM = getBean(LedgerService.class).summary(MapUtil.mapper("company.id", purchaseReturn.getCompany().getId(), "partner.id", purchaseReturn.getSupplier().getId(),
                    "inventoryMode", purchaseReturn.getCooperation().getInventoryMode()));

            if (ledgerMoneyM.containsKey("current_unsettled") && purchaseReturn.compute() > Double.parseDouble(ledgerMoneyM.get("current_unsettled").toString())) {
                purchaseReturn.setState("financeApprove");
                String note = purchaseReturn.getNote() != null ? purchaseReturn.getNote() : "";
                note += "       返厂金额大于供应商：" + purchaseReturn.getSupplier().getName() + "的应付账款，待财务审核！" + DateUtil.format(new Date(), DateUtil.SHOW_DATETIME_FORMAT);
                purchaseReturn.setNote(note);
                return purchaseReturnRepository.saveAndFlush(purchaseReturn);
            }
        }

        return invoke("purchase.return.approve", MapUtil.mapped(purchaseReturn));
    }

    /**
     * 驳回
     * @param request
     */
    public PurchaseReturn dismiss(SimpleRequest request) {
        PurchaseReturn purchaseReturn = request.getO(PurchaseReturn.class);
        purchaseReturn.setState("sent");
        return purchaseReturnRepository.saveAndFlush(purchaseReturn);
    }

    /**
     * 财务不同意
     * @param request
     */
    public PurchaseReturn financeDisagree(SimpleRequest request) {
        PurchaseReturn purchaseReturn = request.getO(PurchaseReturn.class);
        purchaseReturn.setState("apply");
        return purchaseReturnRepository.saveAndFlush(purchaseReturn);
    }

    public JSONObject doupComputeTaxAmount(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        System.out.println("----------");
        JSONObject conditionO = getJO.getJSONObject("condition");
        JSONObject conditionModelO = getJO.getJSONObject("conditionModel");
        Map priceO = invoke("account.tax.computeTaxAmount",
                MapUtil.mapper("companyId", conditionModelO.getJSONObject("company").getString("id"),
                        "taxId", conditionO.getJSONObject("tax").getString("id"),
                        "priceUnit", conditionO.getDoubleValue("taxCostPrice"),
                        "qty", 1
                ));
        conditionO.putAll(priceO);
        return conditionO;
    }

    // 查询批次：入口
    public Page<InventoryBatch> findByPurchaseReturnInventory(SimpleRequest request) {
        // 拼接条件
        Map condi = this.findInventoryCondi(request);

        List<Stock> stocks = stockRepository.findAll(((Group) condi.get("stocks")).build(false));
        if (stocks.isEmpty()) throw  new RuntimeException("未找到可用数大于 0 的库存");
        List<InventoryBatch> inventoryBatches = inventoryBatchRepository.findAll(((Group)condi.get("inventoryGroup")).build(false));

        // 库存 + 批次 匹配
        List<InventoryBatch> inventoryBatcheList = this.findInventoryStockMate(inventoryBatches, stocks, (AtomicReference) condi.get("voucherOrigin"));

        // 分页返回
        int page = (Integer) condi.get("page");
        int size = (Integer) condi.get("size");
        int inventoryBatchSize = inventoryBatcheList.size();
        int subEnd = (page + 1) * size > inventoryBatchSize?inventoryBatchSize:(page + 1) * size;
        PageImpl inventoryValid = new PageImpl(inventoryBatcheList.subList(page * size, subEnd), PageRequest.of(page, size), inventoryBatchSize);
        return inventoryValid;
    }

    // 查询批次：库存 + 批次 匹配
    private List<InventoryBatch> findInventoryStockMate(List<InventoryBatch> inventoryBatches, List<Stock> stocks, AtomicReference voucherOrigin) {
        return inventoryBatches
            .stream()
            .filter(inventoryBatch -> {
                // 获取凭证 origin
                if (StringUtils.isEmpty(inventoryBatch.getVoucherOrigin())) {
                    inventoryBatch.setVoucherOrigin(voucherItemRepository.findOne(inventoryBatch.getBatchNumber()).getVoucher().getOrigin());
                }

                // 获取可用数、可退货数
                for (Stock stock : stocks) {
                    if (inventoryBatch.getProduct().getId().equals(stock.getProduct().getId())) {
                        double canReturnQty = inventoryBatch.getBalanceQty() - inventoryBatch.getFrostQty();
                        inventoryBatch.setUsableQty(stock.getUsableQty());
                        inventoryBatch.setCanReturnQty(stock.getUsableQty() > canReturnQty ? canReturnQty : stock.getUsableQty());
                        break;
                    }
                }

                // 需要根据批次来源查时，匹配批次来源返回
                boolean balanceQtyGtZeroFlag = inventoryBatch.getBalanceQty() - inventoryBatch.getFrostQty() > 0;
                if (!StringUtils.isEmpty(voucherOrigin.get())) {
                    return balanceQtyGtZeroFlag && voucherOrigin.get().equals(inventoryBatch.getVoucherOrigin());
                }
                return balanceQtyGtZeroFlag;
            }).collect(Collectors.toList());

    }

    // 查询批次：拼接条件
    private Map findInventoryCondi(SimpleRequest request) {
        JSONObject getJO = JSON.parseObject(request.getData().toString());
        int size = getJO.getIntValue("size");
        int page = getJO.getIntValue("page");

        List newFilters = new ArrayList();
        AtomicReference voucherOrigin = new AtomicReference("");

        /*
         * 界面 批次内码 不弹框输入
         * key、group --> filter
         * */
        JSONObject location = new JSONObject();
        Group group = new Group();
        if (getJO.containsKey("group")) {
            JSONObject groupOrigin = getJO.getJSONObject("group");
            JSONArray filters = groupOrigin.getJSONArray("filters");

            // 1. 过滤批次不需要的字段 2. 存储查询商品库存需要的字段 - finalLocation
            newFilters = new ArrayList();
            formatValidData(filters, newFilters, location);

            // 重新赋值 filters
            group = JSONObject.parseObject(groupOrigin.toString(), Group.class);
            group.getFilters().clear();
            group.setFilters(JSONArray.parseArray(newFilters.toString(), Filter.class));

            String key = getJO.getString("key");
            group.getGroups().get(0).getFilters().clear();
            group.getGroups().get(0).getFilters().addAll(JpaDsl.toFilter( "product.id", "like", key, "product.name", "like", key));

            Pattern p = Pattern.compile("^-?\\d+(\\.\\d+)?$");
            if (p.matcher(key).matches()) {
                group.getGroups().get(0).getFilters().addAll(JpaDsl.toFilter("id", "eq", getJO.getString("key")));
            }
        }

        /*
         * 界面 批次内码 弹框输入
         * domain、conditionModel
         * */
        if (getJO.containsKey("domain")) {
            JSONObject domain = getJO.getJSONObject("domain");
            JSONArray filters = domain.getJSONArray("filters");

            // 1. 过滤批次不需要的字段 2. 存储查询商品库存需要的字段 - finalLocation
            newFilters = new ArrayList();
            this.formatValidData(filters, newFilters, location);

            // 重新赋值 filters
            group = JSONObject.parseObject(domain.toString(), Group.class);
            group.getFilters().clear();
            group.setFilters(JSONArray.parseArray(newFilters.toString(), Filter.class));

            if (getJO.containsKey("condition") && !getJO.getJSONArray("condition").isEmpty()) { // 弹框输入的条件
                newFilters = new ArrayList();
                this.formatValidData(getJO.getJSONArray("condition"), newFilters, voucherOrigin);
                if (!newFilters.isEmpty()) {
                    group.getFilters().addAll(JSONArray.parseArray(newFilters.toString(), Filter.class));
                }
            }
        }


        /*
         * 批量添加批次内码
         * 1. 不输入条件只有 conditionModel
         * 2. 输条件 condition、conditionModel
         * */
        if (!getJO.containsKey("domain") && getJO.containsKey("condition")) {
            JSONArray condition = getJO.getJSONArray("condition");
            if (!condition.isEmpty()) {
                newFilters = new ArrayList();
                this.formatValidData(condition, newFilters, voucherOrigin);
                if (!newFilters.isEmpty()) {
                    List<Filter> filters = JSONArray.parseArray(newFilters.toString(), Filter.class);
                    group.addFilters(filters);
                }
            }
            // 在 conditionModel 获取仓库
            JSONObject conditionModel = getJO.getJSONObject("conditionModel");
            JSONObject condiMLocation = conditionModel.getJSONObject("location");
            String locationId = condiMLocation.getString("id");
            String companyId = condiMLocation.getJSONObject("company").getString("id");
            location.putAll(MapUtil.mapper("field", "location.id", "value", locationId, "operator", "eq"));

            // 查询选择仓库下的批次，必要条件
            group.getFilters().addAll(JpaDsl.toFilter("company.id", "EQ", companyId));
            group.getFilters().addAll(JpaDsl.toFilter("supplier.id", "EQ", conditionModel.getJSONObject("supplier").getString("id")));
            group.getFilters().addAll(JpaDsl.toFilter("cooperation.id", "EQ", conditionModel.getJSONObject("cooperation").getString("id")));
            group.getFilters().addAll(JpaDsl.toFilter("balanceQty", "GT", 0));

//            page = page - 1; // 前端传过来多加了 1
        }


        // 查询库存条件
        List stockFilters = new ArrayList();
        stockFilters.add(JSONObject.parseObject(location.toString(), Filter.class));
        stockFilters.addAll(JpaDsl.toFilter("usableQty", "GT", 0));
        Group stockCondi = new Group();
        stockCondi.setFilters(stockFilters);
        return MapUtil.mapper("stocks", stockCondi, "inventoryGroup", group, "voucherOrigin", voucherOrigin, "page", page, "size", size);
    }

    /**
     * 作用
     * 1. 过滤查询批次不需要的字段
     * 2. 存储查询商品库存需要的字段 - finalLocation
     */
    private void formatValidData(JSONArray oldFilters, List newFilter, JSONObject location) {
        List newFilter1 = oldFilters.stream().filter(filter -> {
            JSONObject filterO = (JSONObject) filter;
            if ("location.id".equals(filterO.getString("field"))) {
                location.putAll(filterO);
                return false;
            }
            return true;
        }).collect(Collectors.toList());
        newFilter.addAll(newFilter1);
    }

    /**
     * 作用
     * 1. 过滤查询批次不需要的字段
     * 2. 根据批次来源单号查，获取来源单号 - voucherOrigin
     */
    private void formatValidData(JSONArray oldFilters, List newFilter, AtomicReference voucherOrigin) {
        List newFilter1 = oldFilters.stream().filter(filter -> {
            JSONObject filterO = (JSONObject) filter;
            if ("voucherOrigin".equals(filterO.getString("field"))) {
                voucherOrigin.set(filterO.getString("value"));
                return false;
            }
            return true;
        }).collect(Collectors.toList());
        newFilter.addAll(newFilter1);
    }



}
